import SimplexNoise from 'simplex-noise'

export function generateTerrain(options = {}) {
  const config = {
    type: options.type || 'grassland',
    size: options.size || 1000,
    seed: options.seed || Math.random(),
    tileSize: 50
  }

  const simplex = new SimplexNoise(config.seed)
  const heightMap = []
  const typeMap = []
  const obstacles = []

  // 生成高度图和地形类型
  for (let x = 0; x < config.size; x += config.tileSize) {
    heightMap[x] = []
    typeMap[x] = []
    for (let y = 0; y < config.size; y += config.tileSize) {
      // 基础高度噪声 - 低频
      const nx = x / config.size - 0.5
      const ny = y / config.size - 0.5
      let height = simplex.noise2D(nx * 3, ny * 3) * 20
      
      // 中频细节
      height += simplex.noise2D(nx * 10, ny * 10) * 5
      
      // 高频细节
      height += simplex.noise2D(nx * 30, ny * 30) * 2

      // 根据地形类型调整
      switch(config.type) {
        case 'snow':
          height += simplex.noise2D(nx * 5, ny * 5) * 30 +
                   simplex.noise2D(nx * 15, ny * 15) * 10
          break
        case 'grassland':
          height += simplex.noise2D(nx * 8, ny * 8) * 10 +
                   simplex.noise2D(nx * 20, ny * 20) * 3
          break
        case 'town':
          height = Math.floor(height / 2) * 2 // 更精细的阶梯化
          height += simplex.noise2D(nx * 25, ny * 25) * 1 // 添加微小变化
          break
        case 'sand':
          height += simplex.noise2D(nx * 10, ny * 10) * 5 +
                   simplex.noise2D(nx * 40, ny * 40) * 1.5 // 沙丘细节
          break
        case 'wetland':
          height -= 5 + simplex.noise2D(nx * 6, ny * 6) * 10 +
                   simplex.noise2D(nx * 18, ny * 18) * 3 // 水波效果
          break
      }

      heightMap[x][y] = height
      typeMap[x][y] = config.type

      // 随机生成障碍物
      if (Math.random() < getObstacleProbability(config.type)) {
        obstacles.push({
          x,
          y,
          type: getRandomObstacleType(config.type),
          height: height + 10 + Math.random() * 20
        })
      }
    }
  }

  return {
    getHeightAt(x, y) {
      // 三次样条插值
      const tx = x / config.tileSize
      const ty = y / config.tileSize
      const x0 = Math.floor(tx) * config.tileSize
      const y0 = Math.floor(ty) * config.tileSize
      
      // 边界检查
      if (x0 < 0 || y0 < 0 || 
          x0 >= config.size - config.tileSize || 
          y0 >= config.size - config.tileSize) {
        return 0
      }

      // 获取周围16个点(4x4网格)
      const points = []
      for (let i = -1; i <= 2; i++) {
        points[i+1] = []
        const xi = x0 + i * config.tileSize
        for (let j = -1; j <= 2; j++) {
          const yj = y0 + j * config.tileSize
          points[i+1][j+1] = heightMap[xi]?.[yj] || 0
        }
      }

      // 归一化坐标
      const dx = tx - Math.floor(tx)
      const dy = ty - Math.floor(ty)

      // 三次样条插值
      function cubicInterpolate(p, x) {
        return p[1] + 0.5 * x * (p[2] - p[0] + 
               x * (2*p[0] - 5*p[1] + 4*p[2] - p[3] + 
               x * (3*(p[1] - p[2]) + p[3] - p[0])));
      }

      // 先对每行进行插值
      const rowResults = []
      for (let i = 0; i < 4; i++) {
        rowResults[i] = cubicInterpolate(points[i], dx)
      }

      // 再对列进行插值
      return cubicInterpolate(rowResults, dy)
    },
    getTypeAt(x, y) {
      const tx = Math.floor(x / config.tileSize) * config.tileSize
      const ty = Math.floor(y / config.tileSize) * config.tileSize
      return typeMap[tx][ty] || 'grassland'
    },
    getObstacles() {
      return obstacles
    },
    getConfig() {
      return config
    }
  }
}

function getObstacleProbability(terrainType) {
  // 基于地形类型计算概率
  const probabilities = {
    snow: 0.05,
    grassland: 0.1,
    town: 0.3,
    sand: 0.07,
    wetland: 0.15
  };
  
  // 添加基于时间的随机变化
  const timeFactor = (Date.now() % 10000) / 10000;
  let probability = probabilities[terrainType] || 0.1;
  
  // 调整概率范围在±25%内波动
  probability = probability * (0.75 + 0.5 * timeFactor);
  
  // 确保概率在合理范围内
  return Math.max(0.01, Math.min(0.5, probability));
}

function getRandomObstacleType(terrainType) {
  // 带权重的障碍物类型
  const weightedTypes = {
    snow: [
      {type: 'rock', weight: 0.4},
      {type: 'ice', weight: 0.3}, 
      {type: 'tree', weight: 0.3}
    ],
    grassland: [
      {type: 'bush', weight: 0.5},
      {type: 'tree', weight: 0.3},
      {type: 'rock', weight: 0.2}
    ],
    town: [
      {type: 'building', weight: 0.6},
      {type: 'car', weight: 0.3},
      {type: 'fence', weight: 0.1}
    ],
    sand: [
      {type: 'cactus', weight: 0.5},
      {type: 'rock', weight: 0.3},
      {type: 'dune', weight: 0.2}
    ],
    wetland: [
      {type: 'log', weight: 0.4},
      {type: 'rock', weight: 0.3},
      {type: 'reed', weight: 0.3}
    ]
  };

  const available = weightedTypes[terrainType] || [{type: 'rock', weight: 1}];
  
  // 根据权重随机选择
  let totalWeight = available.reduce((sum, item) => sum + item.weight, 0);
  let random = Math.random() * totalWeight;
  let currentWeight = 0;

  for (const item of available) {
    currentWeight += item.weight;
    if (random <= currentWeight) {
      return item.type;
    }
  }
  
  return 'rock'; // 默认值
}
